package featuresWindows;

import helpFeaturesWindows.HelpHoleWindow;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import features.Block;
import features.ConicalHoleBottom;
import features.Feature;
import features.FlatWithRadiusHoleBottom;

import CAD.MainFrame;
import j3d.J3D;
import sun.awt.geom.Curve;
import visualCAD.ConicalHoleBottomWindowView;

public class CreateConicalHoleBottom extends ConicalHoleBottomWindowView implements ActionListener
{
	private J3D j3d = null;
	private ConicalHoleBottomDinamicTopPanel holeTopPanel;
	private ConicalHoleBottomDinamicBottomPanel holeBottomPanel;
	double positionX = 0, positionY = 0, positionZ = 0, radius = 0, depth = 0, tipAngle;
	public CreateConicalHoleBottom(J3D j3d, Block block)
	{
		super();
		this.setVisible(true);
		this.pack();
		this.j3d = j3d;
		this.splitPane1.setDividerLocation(0.5);
		this.splitPane1.setTopComponent(holeTopPanel = new ConicalHoleBottomDinamicTopPanel(
				positionX, positionY, radius, tipAngle));
		this.splitPane1.setBottomComponent(holeBottomPanel = new ConicalHoleBottomDinamicBottomPanel(
				positionX, positionZ, 2 * radius, depth, tipAngle));
		init();
	}
	public void init() {
		double y = holeTopPanel.faceY;
		double x = holeTopPanel.faceX;
		double z = holeTopPanel.faceZ;
		double dLimit;
	
		if(x>=y){
			dLimit = x;
		}else{
			dLimit = y;
		}
		
		//fLimit = radius;
		
		/*SpinnerModel zModel = new SpinnerNumberModel(0.0, -z, 0.0, 0.1);
		SpinnerModel yModel = new SpinnerNumberModel(0.0, 0.0, y, 0.1);
		SpinnerModel xModel = new SpinnerNumberModel(0.0, 0.0, x, 0.1);
		SpinnerModel depthModel = new SpinnerNumberModel(0.0, 0.0, z, 0.1);
		SpinnerModel diameterModel = new SpinnerNumberModel(0.0, 0.0, dLimit, 0.1);
		SpinnerModel tipAngleModel = new SpinnerNumberModel(0.0, 0.0, null, 0.1);
		spinner3.setModel(zModel);
		spinner1.setModel(xModel);
		spinner2.setModel(yModel);
		spinner6.setModel(depthModel);
		spinner4.setModel(diameterModel);
		spinner7.setModel(tipAngleModel);*/

		this.spinner4.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});
		this.spinner7.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});
		spinner2.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});
		spinner3.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});
		spinner1.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});
		spinner6.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});
		/*checkBox1.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});

		optionalLateralSpinner.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});
		optionalFloorSpinner.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				redrawDynamicComponents();
			}
		});*/

		this.button1.addActionListener(this);
		this.okButton.addActionListener(this);
		this.cancelButton.addActionListener(this);
		this.setResizable(false);
	}
	private void redrawDynamicComponents() {
		try {
			radius = (Double) spinner4.getValue() / 2;		
			tipAngle = (Double) spinner7.getValue();
			positionX = (Double) spinner1.getValue();
			positionY = (Double) spinner2.getValue();
			positionZ = (Double) spinner3.getValue();
			depth = (Double) spinner6.getValue();
			/*check = checkBox1.getSelectedIcon();
			if (checkBox1.isSelected()) {
				optionalLateralSpinner.setEnabled(true);
				optionalFloorSpinner.setEnabled(true);
				optionalLateral = (Double) optionalLateralSpinner.getValue();
				optionalFloor = (Double) optionalFloorSpinner.getValue();
			} else {
				optionalLateralSpinner.setEnabled(false);
				optionalFloorSpinner.setEnabled(false);
			}*/

		} catch (Exception e1) {
			JOptionPane.showMessageDialog(null, "error in entering data");
		}
		this.splitPane1.setTopComponent(holeTopPanel = new ConicalHoleBottomDinamicTopPanel(
						positionX, positionY, radius, tipAngle));
		splitPane1.setBottomComponent(holeBottomPanel = new ConicalHoleBottomDinamicBottomPanel(
						positionX, positionZ, 2 * radius, depth, tipAngle));
		splitPane1.setDividerLocation(0.5);
	}

	public void cancel() {
		this.dispose();
	}

	public void ok() {
		boolean ok = true;

		// ----------- positionX validation -----------//

		if (ok) {
			try {
				positionX = (Double) this.spinner1.getValue();
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, "error in entering data");
				ok = false;
			}
		}

		// ------------- positionY validation ------------//

		if (ok) {
			try {
				positionY = (Double) this.spinner3.getValue();
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, "error in entering data");
				ok = false;
			}
		}
		// ------------- positionZ validation -------------//

		if (ok) {
			try {
				positionZ = -(Double) this.spinner2.getValue();
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, "error in entering data");
				ok = false;
			}
		}
		// -------------- radius Validation ---------------//
		if (ok) {
			try {
				radius = (Double) this.spinner4.getValue() / 2;
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, "error in entering data");
				ok = false;
			}
		}
		// -------------- floorRadius Validation ---------------//
		if (ok) {
			try {
				tipAngle = (Double) this.spinner7.getValue();
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, "error in entering data");
				ok = false;
			}
		}
		// -------------- depth Validation ---------------//
		if (ok) {
			try {
				depth = (Double) this.spinner6.getValue();
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, "error in entering data");
				ok = false;
			}
		}
		// -------------- check Validation ---------------//
		/*if (ok) {
			try {
				check = checkBox1.getSelectedIcon();
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, "error in entering data");
				ok = false;
			}
		}
		// -------------- optionalLateral Validation ---------------//
		/*if (ok) {
			try {
				optionalLateral = (Double) optionalLateralSpinner.getValue();
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, "error in entering data");
				ok = false;
			}
		}
		// -------------- optionalFloor Validation ---------------//
		if (ok) {
			try {
				optionalFloor = (Double) optionalFloorSpinner.getValue();
			} catch (Exception e) {
				JOptionPane.showMessageDialog(null, "error in entering data");
				ok = false;
			}
		}*/
		if (ok) {

			ConicalHoleBottom hole = new ConicalHoleBottom(
					Feature.CONICALHOLEBOTTOM, null, this.textField1.getText(),
					(float) (radius), (float)depth,  (float) (positionX),
					(float) (positionY), (float) (positionZ), (float)tipAngle, MainFrame.Face);
			
			this.j3d.removeSolid();
			this.j3d.addSolid(MainFrame.block.block);
			this.dispose();

		}
	}

	
	
	@Override
	public void actionPerformed(ActionEvent event) 
	{
		Object origin = event.getSource();

		if (origin.equals(cancelButton)) {
			this.cancel();
		} else if (origin.equals(okButton)) {
			this.ok();
		} else if (origin.equals(button1)) {
			new HelpHoleWindow();
		}
	}
}
class ConicalHoleBottomDinamicTopPanel extends JComponent {

	Shape bigHole;
	//Shape smallHole;
	Shape box;
	Shape axisX, axisY;
	double faceX = 0;
	double faceY = 0;
	double faceZ = 0;
	double multiplier = 0;
	double positionX, positionY, radius, tipAngle = 0;

	private void findXandY() {
		switch (MainFrame.Face) {
		case MainFrame.TOPFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.length;
			faceZ = MainFrame.block.height;
			break;
		case MainFrame.LOWERFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.length;
			faceZ = MainFrame.block.height;
			break;
		case MainFrame.FRONTFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.length;
			break;
		case MainFrame.BACKFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.length;
			break;
		case MainFrame.EASTFACE:
			faceX = MainFrame.block.length;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.width;
			break;
		case MainFrame.WESTFACE:
			faceX = MainFrame.block.length;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.width;
			break;
		}
	}

	private double calculateMultiplier() {
		double multiplier = 195 / faceY;
		if (faceX * multiplier > 370) {
			multiplier = 370 / faceX;
		}
		if (faceZ * multiplier > 180) {
			multiplier = 180 / faceZ;
		}
		return multiplier;
	}

	public ConicalHoleBottomDinamicTopPanel(double positionX, double positionY,	double radius, double tipAngle) {
		super();
		findXandY();
		multiplier = calculateMultiplier();
		this.positionX = positionX;
		this.positionY = positionY;
		this.radius = radius;
		this.tipAngle = tipAngle;

		//double bottomRadius = radius - tipAngle;

		bigHole = createHole(multiplier * (positionX),
				multiplier * (positionY), multiplier * (radius));
		//smallHole = createHole(multiplier * (positionX), multiplier	* (positionY), multiplier * (bottomRadius));
		box = createRectangle();
		axisX = verticalLine();
		axisY = horizontalLine();
	}

	protected Shape createHole(double posX, double posY, double radius) {
		Shape circle = new Ellipse2D.Double((posX + 10 - radius),
				(posY + 20 - radius), radius * 2, radius * 2);
		return circle;
	}

	protected Shape createRectangle() {
		Shape rectangle = new Rectangle2D.Double(10, 20, faceX * multiplier,
				faceY * multiplier);
		return rectangle;
	}

	protected Shape verticalLine() {

		Shape axisY = new Line2D.Double(10, 20, 10, 50);
		return axisY;
	}

	protected Shape horizontalLine() {
		Shape axisX = new Line2D.Double(10, 20, 50, 20);
		return axisX;
	}

	public void paint(Graphics g) {
		double translateX, translateY = 0;
		translateY = this.multiplier * faceY;
		// System.out.println("translateY = " + translateY);
		Graphics2D g2 = (Graphics2D) g;
		g2.scale(1, -1);
		g2.translate(0, -215);
		g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
				RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);

		g2.setPaint(new Color(211, 211, 211));
		g2.fill(box);
		g2.setPaint(Color.BLACK);
		g2.draw(box);
		g2.setPaint(new Color(135, 206, 250));
		g2.fill(bigHole);
		g2.setPaint(Color.BLUE);
		g2.draw(bigHole);

		g2.setStroke(new BasicStroke(0.65f, BasicStroke.CAP_BUTT,
				BasicStroke.JOIN_MITER));
		g2.setColor(Color.BLUE);
		//g2.draw(smallHole);
		g2.setStroke(new BasicStroke());

		g2.setPaint(Color.RED);
		g2.draw(axisX);
		g2.draw(axisY);
		g2.scale(1, -1);
		g2.drawString("X", 50, -10);
		g2.drawString("Y", 0, -50);
		int x = (int) (multiplier * (positionX));
		int y = (int) (multiplier * (positionY));
		g2.drawString("x", x + 8, -y - 16);

	}
}

class ConicalHoleBottomDinamicBottomPanel extends JComponent 
{

	Shape smallBox1;
	Shape bigBox;
	Shape axisX, axisY, centerLine;
	double faceX = 0;
	double faceY = 0;
	double faceZ = 0;
	double multiplier = 0;

	private void findXandY() {
		switch (MainFrame.Face) {
		case MainFrame.TOPFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.length;
			faceZ = MainFrame.block.height;
			break;
		case MainFrame.LOWERFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.length;
			faceZ = MainFrame.block.height;
			break;
		case MainFrame.FRONTFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.length;
			break;
		case MainFrame.BACKFACE:
			faceX = MainFrame.block.width;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.length;
			break;
		case MainFrame.EASTFACE:
			faceX = MainFrame.block.length;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.width;
			break;
		case MainFrame.WESTFACE:
			faceX = MainFrame.block.length;
			faceY = MainFrame.block.height;
			faceZ = MainFrame.block.width;
			break;
		}
	}

	private double calculateMultiplier() {
		double multiplier = 195 / faceY;
		if (faceX * multiplier > 310) {
			multiplier = 310 / faceX;
		}
		if (faceZ * multiplier > 180) {
			multiplier = 180 / faceZ;
		}
		return multiplier;
	}

	public ConicalHoleBottomDinamicBottomPanel(double positionX, double positionZ,
			double diameter, double depth, double tipAngle) {
		super();
		findXandY();

		multiplier = calculateMultiplier();
		smallBox1 = createBox(multiplier * (positionX - (diameter / 2)),
				multiplier * (-positionZ), multiplier * (diameter), multiplier
						* (depth));
		
		bigBox = createRectangle();
		axisX = verticalLine();
		axisY = horizontalLine();
		centerLine = centerLine(multiplier * (positionX - (diameter / 2)),
				multiplier * (-positionZ), multiplier * (diameter), multiplier
						* (depth));
	}

	protected Shape createBox(double posX, double posY, double d1, double d2) {
		Shape rectangle = new Rectangle2D.Double(10 + posX, 20 + posY, d1, d2);
		return rectangle;
	}

	protected Shape createRectangle() {
		Shape rectangle = new Rectangle2D.Double(10, 20, faceX * multiplier,
				faceZ * multiplier);
		return rectangle;
	}

	protected Shape createHole(double posX, double posY, double radius) {
		Shape circle = new Ellipse2D.Double((posX + 10 - radius),
				(posY + 20 - radius), radius * 2, radius * 2);
		return circle;
	}

	protected Shape verticalLine() {

		Shape axisY = new Line2D.Double(10, 20, 10, 50);
		return axisY;
	}

	protected Shape horizontalLine() {
		Shape axisX = new Line2D.Double(10, 20, 50, 20);
		return axisX;
	}

	protected Shape centerLine(double posX, double posY, double d1, double depth) {
		Shape axisX = new Line2D.Double(10 + posX + (d1 / 2), 20 + posY, 10
				+ posX + (d1 / 2), 20 + posY + depth);
		return axisX;
	}

	public void paint(Graphics g) {
		// System.out.println("translateY = " + translateY);
		Graphics2D g2 = (Graphics2D) g;
		g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
				RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);
		float dash1[] = { 2.5f, 2.5f };
		float dash2[] = { 3f, 1.5f, 1f, 1.5f };
		g2.setPaint(new Color(211, 211, 211));
		g2.fill(bigBox);

		g2.setPaint(Color.BLUE);
		g2.setStroke(new BasicStroke(1f, BasicStroke.CAP_BUTT,
				BasicStroke.JOIN_MITER, 10.0f, dash1, 0.0f));
		
		g2.setPaint(new Color(135, 206, 250));
		g2.fill(smallBox1);
	
		g2.setPaint(Color.BLUE);
		g2.draw(smallBox1);

		g2.setPaint(Color.BLACK);
		g2.setStroke(new BasicStroke());
		g2.draw(bigBox);
		g2.setPaint(Color.RED);
		g2.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_BUTT,
				BasicStroke.JOIN_MITER, 10.0f, dash2, 0.0f));
		g2.draw(centerLine);
		g2.setStroke(new BasicStroke(1f, BasicStroke.CAP_ROUND,
				BasicStroke.JOIN_ROUND));
		g2.draw(axisX);
		g2.draw(axisY);
		g2.drawString("X", 50, 20);
		g2.drawString("-Z", 0, 50);
		
		//falta desenhar a ponta do triangulo!!!!
	}
}